/***************************************************************************
 * Copyright 2012-2013 TXT e-solutions SpA
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the contract ICT-257367.
 *
 * Authors:
 *      Salvatore Piccione (TXT e-solutions SpA)
 *
 * Contributors:
 *        Domenico Rotondi (TXT e-solutions SpA)
 **************************************************************************/
package it.txt.ens.client.subscriber.printer;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Map.Entry;

import it.txt.ens.client.core.ENSEvent;
import it.txt.ens.client.subscriber.ENSSubscriber;
import it.txt.ens.client.subscriber.ENSEventListener;

/**
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT txtgroup.com)
 * @author Domenico Rotondi (TXT e-solutions SpA - domenico.rotondi AT txtgroup.com)
 *
 */
public class ENSEventPrinterImpl implements ENSEventPrinter{
    
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS Z";
    
    public static String eventToString (ENSEvent event) {
        StringBuilder builder = new StringBuilder();
        builder.append("ENS Event: {");
        builder.append("timestamp: ");
        if (event.getTimestamp() != null) {
            builder.append(new SimpleDateFormat(DATE_TIME_FORMAT).format(event.getTimestamp()));
        } else
            builder.append((String)null);
        builder.append("\", applicationID: \"");
        builder.append(event.getApplicationID());
        builder.append("\", contentType: \"");
        builder.append(event.getContentType());
        builder.append("\", contentEncoding: \"");
        builder.append(event.getContentEncoding());
        builder.append("\", pattern: \"");
        builder.append(event.getPattern());
        builder.append("\", priority: ");
        builder.append(event.getPriority());
        builder.append(", ");
        if (event.getPayload() == null) {
            builder.append("body: null");
        } else {
            builder.append("bodySize: ");
            builder.append(event.getPayload().length);
            builder.append(" byte");
            
            if (event.getContentType().startsWith("text")) {
                builder.append(", body: ");
                try {
                    String payload = new String(event.getPayload(), event.getContentEncoding());
                    builder.append(payload);
                } catch (UnsupportedEncodingException e) {
                    builder.append("\"unsupported content encoding\"");
                }
            }
        }
        
        builder.append(", headers: ");
        if (event.getHeaders() == null) {
            builder.append("null");
        } else {
            builder.append("{");
            for (Entry<String,Object> entry : event.getHeaders().entrySet()) {
                builder.append(", ");
                builder.append(entry.getKey());
                builder.append(": \"");
                builder.append(entry.getValue());
                builder.append("\"");
            }
            builder.append("}");
        }
        builder.append("}");
        return builder.toString();
    }
    
    private final ENSSubscriber subscriber;
    private final String id;
    private final String listenerID;
    
    public ENSEventPrinterImpl (String id, ENSSubscriber subscriber) {
        this.subscriber = subscriber;
        this.id = id;
        this.listenerID = subscriber.registerEventListener(new ENSEventListener() {
            @Override
            public void onEvent(ENSEvent event) {
                System.out.println(ENSEventPrinterImpl.this.id + ":: " + eventToString(event));
            }
        });
    }

    /* (non-Javadoc)
     * @see it.txt.ens.client.subscriber.printer.ENSEventPrinter#start()
     */
    @Override
    public void start() throws Exception {
        subscriber.subscribe();
    }

    /* (non-Javadoc)
     * @see it.txt.ens.client.subscriber.printer.ENSEventPrinter#stop()
     */
    @Override
    public void stop() throws Exception {
        subscriber.unsubscribe();
    }

    public boolean isWorking () {
        return subscriber.isSubscribed();
    }

    /* (non-Javadoc)
     * @see it.txt.ens.client.subscriber.printer.ENSEventPrinter#shutdown()
     */
    @Override
    public void shutdown() throws Exception {
        subscriber.disconnect();
        subscriber.unregisteredEventListener(listenerID);
    }

    /* (non-Javadoc)
     * @see it.txt.ens.client.subscriber.printer.ENSEventPrinter#init()
     */
    @Override
    public void init() throws Exception {
        subscriber.connect();
    }

    /* (non-Javadoc)
     * @see it.txt.ens.client.subscriber.printer.ENSEventPrinter#isInitialised()
     */
    @Override
    public boolean isInitialised() {
        return subscriber.isConnected();
    }

    /**
     * @return
     */
    public String getID() {
        return id;
    }
}
